home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Collections: Taifun
/
Taifun 054 (1988-05-15)(Ossowski, Stefan)(DE)(PD).zip
/
Taifun 054 (1988-05-15)(Ossowski, Stefan)(DE)(PD).adf
/
MRBackup
/
MRBackup2.0
/
Restore.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-04-09
|
10KB
|
390 lines
/* Filename: restore.c
* Author: Mark R. Rinfret
* Date: 08/02/87
* Description: Restore processing module for MRBackup
*
* History: (most recent change first)
*
* 12/18/87 -MRR- Restore was using function IsCompressed() to determine
* candidates for decompression. Unfortunately, it also
* tried to decompress .ARC and .ZOO files.
*
* Restore now requests the next disk to be restored from.
*
* 11/22/87 -MRR- Modifications for version 2.0.
*
* 09/19/87 -MRR- Added NewHomeDir() which creates subdirectories as
* necessary when the initial backup path specifies a
* subdirectory.
*/
#include "MRBackup.h"
#include ":src/lib/DiskMisc.h"
char fullBackPath[PATH_MAX+1], fullHomePath[PATH_MAX+1];
static BOOL bigFileSeqNbr; /* >0 => big file sequence number */
BOOL homeIsDevice; /* true => home is "DH<N>:" */
^L
/* Create a new directory on the home device.
* Called with:
* name: directory pathname
* Returns:
* false => success
* true => failure
*/
int
NewHomeDir(name)
char *name;
{
char c;
struct Lock *dirLock;
int dirLeng;
int errnum;
char dirname[256];
int nameindx = 0, nameleng;
*dirname = '\0';
dirLeng = 0;
nameleng = strlen(name);
/* Parse the pathname, one directory node at a time, creating
* directories as needed.
*/
while (nameindx < nameleng) {
if (nameindx) /* 2nd - nth pass? */
dirname[dirLeng++] = '/'; /* directory separator */
while ((c = name[nameindx++]) && c != '/')
dirname[dirLeng++] = c;
dirname[dirLeng] = '\0'; /* terminate with null */
if (dirLock = (struct Lock *)
Lock(dirname,SHARED_LOCK)) /* subdir exists? */
UnLock(dirLock);
else { /* create subdirectory */
if ((dirLock = (struct Lock *) CreateDir(dirname))== NULL){
if ((errnum = IoErr())== ERROR_DIRECTORY_NOT_EMPTY){
sprintf(conmsg,
"Directory %s already exists!\n",dirname);
TypeAndSpeak(conmsg);
}
else {
sprintf(conmsg,
"ERROR %d: Unable to create directory %s\n",
errnum,dirname);
TypeAndSpeak(conmsg);
return errnum;
}
}
else
UnLock(dirLock);
}
} /* endwhile */
return 0;
}
/* Restore files from floppy disk. */
int
Restore()
{
int disks=0, status = 0;
char volumeName[31];
Speak("And away we go!");
BreakPath(backPath, srcVol, srcPath);
strcat(srcVol, ":");
homeIsDevice = (homePath[strlen(homePath)-1] == ':');
BreakPath(homePath, destVol, destPath);
strcat(destVol, ":");
while ( !status ) {
TypeAndSpeak("I am ready to read the next disk.\n");
if (!RequestDisk(mainWindow, srcVol,
"Insert the next disk to be restored in "))
break;
if (!IsDir(backPath)) {
TypeAndSpeak(
"Backup path must be a device or directory name!\n");
return ERR_ABORT;
}
GetVolumeName(srcVol, volumeName);
SetCurVolumeGadget(volumeName);
if ( (totalSize = TotalDiskBlocks(destVol)) < 0)
status = -totalSize;
else if ((bigFileSeqNbr = GetBigFileInfo(srcVol)) < 0)
status = -bigFileSeqNbr;
else {
status = RestoreFile(srcPath);
}
if (bigFileSeqNbr) { /* we have a big file to restore? */
status = RestoreBigFile();
}
/*!!! Need GetErrOpt right here... */
++disks;
}
if (status == 0) {
if (disks)
TypeAndSpeak("Your restoration project is completed.\n");
else
TypeAndSpeak("Maybe you will let me do it next time.\n");
}
else {
sprintf(conmsg,"Restore terminated with status %d.\n",status);
TypeAndSpeak(conmsg);
TypeAndSpeak(
"Perhaps you should check things out and try it again.\n");
}
SetCurVolumeGadget("");
return status;
}
^L
/* Restore all the files in a directory.
* Called with:
* lock: lock on the directory
* fib: pointer to file info block
* path: directory pathname (without volume)
* Returns:
* status (0 => success)
*/
int
RestoreDir(lock, fib, path)
struct Lock *lock; struct FileInfoBlock *fib; char *path;
{
struct Lock *dirLock = NULL, *filelock = NULL;
char newpath[256];
int status = 0;
strcpy(temp, homePath);
if (*path) {
if (!homeIsDevice) strcat(temp, "/");
strcat(temp, path);
}
#ifdef DEBUG
sprintf(debugMsg,"Checking for directory %s\n",temp);
DebugWrite(debugMsg);
#endif
if (!(dirLock = (struct Lock *) Lock(temp, SHARED_LOCK))) {
if ((status = IoErr()) == ERROR_OBJECT_NOT_FOUND) {
#ifdef DEBUG
sprintf(debugMsg,"Creating directory %s\n",temp);
DebugWrite(debugMsg);
#endif
if (status = NewHomeDir(temp))
return status;
}
else {
sprintf(conmsg,"RestoreDir cannot lock %s: %d\n",temp, status);
TypeAndSpeak(conmsg);
return status;
}
}
if (dirLock) UnLock(dirLock);
while (ExNext(lock,fib)) {
strcpy(newpath, path);
if (*newpath)
strcat(newpath, "/");
strcat(newpath, fib->fib_FileName);
if (status = RestoreFile(newpath)) {
/* filter out "permissable:" errors */
if (status == ERROR_OBJECT_IN_USE ||
status == ERROR_WRITE_PROTECTED)
status = 0;
else
break;
}
}
done:
return status;
}
^L
/* Restore one or more files according to the calling pathname.
* The path argument does not contain the backup volume name.
*/
int
RestoreFile(path)
char *path;
{
struct FileInfoBlock *fib = NULL, *fib2 = NULL;
UBYTE exists = FALSE, ignore = FALSE;
unsigned isCompressed;
struct Lock *lock = NULL;
USHORT nameLength;
char *s;
UBYTE savechar;
int status = 0;
if (status = CheckStop()) return status;
/* Don't restore the big file here...it's done last. */
if (ThisIsBigFile(path)) return status;
if (!(fib = (struct FileInfoBlock *)
AllocMem((long) sizeof (struct FileInfoBlock),
MEMF_PUBLIC | MEMF_CHIP))) {
TypeAndSpeak("RestoreFile could not allocate FIB!\n");
return ERROR_NO_FREE_STORE;
}
sprintf(fullBackPath, "%s%s",srcVol,path);
strcpy(fullHomePath, homePath);
if (*path) {
if (!homeIsDevice) strcat(fullHomePath, "/");
strcat(fullHomePath, path);
}
#ifdef DEBUG
sprintf(conmsg,"fullBackPath = %s\n",fullBackPath);
DebugWrite(conmsg);
sprintf(conmsg,"fullHomePath = %s\n",fullHomePath);
DebugWrite(conmsg);
#endif
if ((sizeLeft = DiskBlocksLeft(destVol)) < 0) {
status = -sizeLeft;
sprintf(conmsg,
"Can't determine disk blocks left on %s; error %d.\n",
destVol, status);
TypeAndSpeak(conmsg);
goto done;
}
SetGauge(sizeLeft, totalSize);
do {
status = 0;
if (!(lock = (struct Lock *) Lock(fullBackPath, SHARED_LOCK))) {
status = IoErr();
sprintf(conmsg, "RestoreFile can't lock %s; error %d\n",
fullBackPath, status);
TypeAndSpeak(conmsg);
goto checkStatus;
}
if (!Examine(lock, fib)) {
status = IoErr();
sprintf(conmsg, "RestoreFile can't examine %s; error %d\n",
fullBackPath, status);
TypeAndSpeak(conmsg);
goto checkStatus;
}
if (fib->fib_DirEntryType > 0) { /* path is a directory */
status = RestoreDir(lock, fib, path);
UnLock(lock);
lock = NULL;
}
else {
UnLock(lock);
lock = NULL;
/* Note: though we can use the function IsCompressed to test
* for potentially compressed files in Backup(), ONLY files
* compressed with LZW (ending in .z) are candidates for
* decompression. The following test looks for these files
* only.
*/
isCompressed = false;
if (doCompress && (s = rindex(fullHomePath,'.'))) {
/* look for ".z" ONLY! */
if (!strcmpc(s, ".z")) {
isCompressed = true;
/* truncate the destination pathname (remove ".z") */
nameLength = strlen(fullHomePath);
fullHomePath[nameLength-2] = '\0';
}
}
/*#define NOCOPY*/
#ifndef NOCOPY
/* If this file exists, then check its modification date. If
* it's newer than the backup, don't replace it.
*/
if ((lock = (struct Lock *) Lock(fullHomePath, SHARED_LOCK))) {
if (!(fib2 = (struct FileInfoBlock *)
AllocMem((long) sizeof (struct FileInfoBlock),
MEMF_PUBLIC | MEMF_CHIP))) {
TypeAndSpeak("RestoreFile could not allocate FIB!\n");
status = ERROR_NO_FREE_STORE;
goto done;
}
Examine(lock, fib2);
UnLock(lock);
lock = NULL;
if (CompareDS(&fib2->fib_Date, &fib->fib_Date) >= 0)
ignore = TRUE;
}
if (ignore) {
sprintf(conmsg,
"Skipping %s, since home file is current.\n",
path);
WriteConsole(conmsg);
}
else {
if (! (doCompress && isCompressed) ) {
copyfile:
sprintf(conmsg,"Copying %s\n", fullBackPath);
WriteConsole(conmsg);
status = CopyFile(fullBackPath, fullHomePath);
}
else {
sprintf(conmsg, "Decompressing %s\n", fullBackPath);
WriteConsole(conmsg);
if (status = decompress(fullBackPath, fullHomePath)) {
sprintf(conmsg,
"Decompression of %s failed; status is %d.\n",
fullBackPath, status);
TypeAndSpeak(conmsg);
TypeAndSpeak(
"I will try to copy the file, instead.\n");
/* restore ".z" to name */
fullHomePath[nameLength-2] = '.';
goto copyfile;
}
CopyFileDate(fullBackPath, fullHomePath);
}
}
#endif
}
checkStatus:
if (status && status != ERR_ABORT) {
++errorCount;
SetErrorGadget();
if (status == ERROR_DISK_FULL) {
TypeAndSpeak("The destination disk is full.\n");
/* The following test is pretty kludgy. It boils down to
* "If the drive is a DF<x> device, it's removable, therefore the
* user can recover from this error by inserting a new diskette."
*/
if (toupper(destVol[0]) == 'D' &&
toupper(destVol[1]) == 'F') {
TypeAndSpeak(
"Put a new disk in the destination drive and try again.\n");
}
else {
TypeAndSpeak(
"You may have to delete some files to continue.");
}
}
status = GetErrOpt(ERR_ABORT|ERR_RETRY_FILE|ERR_IGNORE);
if (status == ERR_IGNORE) status = 0;
}
} while (status == ERR_RETRY_FILE);
done:
if (lock) UnLock(lock);
if (fib) FreeMem(fib, (long) sizeof(struct FileInfoBlock));
if (fib2) FreeMem(fib2, (long) sizeof(struct FileInfoBlock));
return status;
}